﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Text.RegularExpressions;

namespace SKDB_Matcher
{
    class CAlgorithm_Content : CAbstractAlgorithm
    {
        public CAlgorithm_Content()
        {
            Weight = 0.4f;
            Caption = "Content";
        }

        public override float[,] CalcMatches(System.Data.DataSet _Source, System.Data.DataSet _Destination)
        {
            float[,] tmp = new float[SourceColumCount, TargetColumCount];
            int n = 0;
            int m = 0;
            foreach (DataTable TableSource in _Source.Tables)
            {
                foreach (DataColumn ColumnSource in TableSource.Columns)
                {
                    m = 0;
                    foreach (DataTable TableDest in _Destination.Tables)
                    {
                        foreach (DataColumn ColumnDest in TableDest.Columns)
                        {
                            tmp[n, m] = CompareContent(ColumnSource, ColumnDest);
                            m++;
                        }
                    }
                    n++;
                }
            }
            return tmp;
        }

        private Boolean ConvertableStringToDecimal(object s, Boolean AllowComma, Boolean AllowMinus = true)
        {
            Boolean Result = true;

            if (s.GetType().Name != "DBNull")
            {
                String word = s.ToString();
                int MinusCount = 0;
                int CommaCount = 0;
                int ValidSigns = 0;

                // Besitzt es ein Minus und ist dieses auch konform (am Anfang)
                foreach (char c in word)
                {
                    if (c == '-')
                        MinusCount++;
                    if ((c == '.') || (c == ','))
                        CommaCount++;
                    if ((c >= 48) && (c <= 59))
                        ValidSigns++;
                }
                if (ValidSigns != word.Length - MinusCount - CommaCount)
                    Result = false;
                if (Result && ((MinusCount > 1) || ((MinusCount == 1) && (word[0] != '-'))))
                    Result = false;
                else
                    if (!AllowMinus)
                        Result = false;
                if (Result && CommaCount > 0)
                    if (AllowComma)
                    {
                        Result = (CommaCount == 1 && word[0] != '.' && word[0] != ',' && word[word.Length - 1] != ',' && word[word.Length - 1] != '.');
                    }
                    else
                        Result = false;
            }
            else
            {
                Result = false;
            }

            return Result;
        }

        private float Abs(float f)
        {
            if (f < 0)
                return -f;
            else 
                return f;
        }

        private float Abs(Double f)
        {
            if (f < 0)
                return (float)-f;
            else
                return (float)f;
        }  


        // Maximal erreichbar 100% -> 1f
        private float CalcMatching(float Source, float Dest)
        {
            float Result = 0.0f;
            if (Source != Dest)
            {
                Result = 1 - (Abs(Source - Dest) / Dest);
            }
            else
                Result = 1f;

            return Result;
        }

        // Maximal erreichbar 100% -> 1f
        private float CalcMatching(Double Source, Double Dest)
        {
            Double Result = 0.0f;
            if (Source != Dest)
            {
                Result = 1 - (Abs(Source - Dest) / Dest);
            }
            else
                Result = 1f;

            return (float)Result;
        }

        private float CompareContent(DataColumn SourceColumn, DataColumn DestColumn)
        {
            DataRowCollection SRows = SourceColumn.Table.Rows;
            DataRowCollection DRows = DestColumn.Table.Rows;
            float Result = 0.0f;

            if (SRows.Count == 0 || DRows.Count == 0)
                return Result;

#region StringToInt32
            // String auf Integer
            if ((SourceColumn.DataType.Name == "String") && (DestColumn.DataType.Name == "Int32"))
            {
                // Strings können nach Int konvertiert werden!?
                Boolean Convertable = true;
                Boolean First = true;
                float SourceAve = 0;
                int SourceMax = 0;
                int SourceMin = 0;


                // Maximal ein Komma/Punkt und ein Minus, Wert muss unter Int.Max liegen
                foreach (DataRow Row in SRows)
                {
                    Boolean Valid = ConvertableStringToDecimal(Row[SourceColumn],false,true);

                    if (!Valid)
                    {
                        Convertable = false;
                        break;
                    }
                    int tmp = Convert.ToInt32(Row[SourceColumn]);
                    SourceAve += tmp;

                    if (First)
                    {
                        SourceMax = tmp;
                        SourceMin = tmp;
                        First = false;
                    }

                    if (tmp > SourceMax)
                        SourceMax = tmp;
                    if (tmp < SourceMin)
                        SourceMin = tmp;

                }
                SourceAve = SourceAve / SRows.Count;

                if (Convertable)
                {
                    float DestAve = 0;
                    int DestMax = 0;
                    int DestMin = 0;
                    First = true;
                    foreach (DataRow Row in DRows)
                    {
                        if (Row[DestColumn].GetType().Name != "DBNull")
                        {
                            int tmp = Convert.ToInt32(Row[DestColumn]);

                            DestAve += tmp;

                            if (First)
                            {
                                DestMax = tmp;
                                DestMin = tmp;
                                First = false;
                            }

                            if (tmp > DestMax)
                                DestMax = tmp;
                            if (tmp < DestMin)
                                DestMin = tmp;
                        }

                    }

                    DestAve = DestAve / DRows.Count;

                    float AverageMatching = CalcMatching(SourceAve, DestAve);
                    float MinMatching = CalcMatching(SourceMin, DestMin);
                    float MaxMatching = CalcMatching(SourceMax, DestMax);


                    Result = (AverageMatching * 0.4f) + (MinMatching * 0.3f) + (MaxMatching * 0.3f);
                }
            }
                #endregion

            #region StringToInt16
            // String auf Integer
            if ((SourceColumn.DataType.Name == "String") && (DestColumn.DataType.Name == "Int16"))
            {
                // Strings können nach Int konvertiert werden!?
                Boolean Convertable = true;
                Boolean First = true;
                float SourceAve = 0;
                int SourceMax = 0;
                int SourceMin = 0;


                // Maximal ein Komma/Punkt und ein Minus, Wert muss unter Int.Max liegen
                foreach (DataRow Row in SRows)
                {
                    Boolean Valid = ConvertableStringToDecimal(Row[SourceColumn], false, true);

                    if (!Valid)
                    {
                        Convertable = false;
                        break;
                    }
                    int tmp = Convert.ToInt32(Row[SourceColumn]);
                    SourceAve += tmp;

                    if (First)
                    {
                        SourceMax = tmp;
                        SourceMin = tmp;
                        First = false;
                    }

                    if (tmp > SourceMax)
                        SourceMax = tmp;
                    if (tmp < SourceMin)
                        SourceMin = tmp;

                }
                SourceAve = SourceAve / SRows.Count;

                if (SourceMax > Int16.MaxValue)
                    Convertable = false;

                if (Convertable)
                {
                    float DestAve = 0;
                    int DestMax = 0;
                    int DestMin = 0;
                    First = true;
                    foreach (DataRow Row in DRows)
                    {
                        if (Row[DestColumn].GetType().Name != "DBNull")
                        {
                            int tmp = Convert.ToInt32(Row[DestColumn]);

                            DestAve += tmp;

                            if (First)
                            {
                                DestMax = tmp;
                                DestMin = tmp;
                                First = false;
                            }

                            if (tmp > DestMax)
                                DestMax = tmp;
                            if (tmp < DestMin)
                                DestMin = tmp;
                        }

                    }

                    DestAve = DestAve / DRows.Count;

                    float AverageMatching = CalcMatching(SourceAve, DestAve);
                    float MinMatching = CalcMatching(SourceMin, DestMin);
                    float MaxMatching = CalcMatching(SourceMax, DestMax);


                    Result = (AverageMatching * 0.4f) + (MinMatching * 0.3f) + (MaxMatching * 0.3f);
                }
            }
            #endregion

#region StringDecimal
            // String - Decimal
            if ((SourceColumn.DataType.Name == "String") && (DestColumn.DataType.Name == "Decimal"))
            {
                // Strings können nach Int konvertiert werden!?
                Boolean Convertable = true;
                Boolean First = true;
                Double SourceAve = 0;
                Double SourceMax = 0;
                Double SourceMin = 0;


                // Maximal ein Komma/Punkt und ein Minus, Wert muss unter Int.Max liegen
                foreach (DataRow Row in SRows)
                {
                    Boolean Valid = ConvertableStringToDecimal(Row[SourceColumn], true, true);

                    if (!Valid)
                    {
                        Convertable = false;
                        break;
                    }
                    Double tmp = Convert.ToDouble(Row[SourceColumn]);
                    SourceAve += tmp;

                    if (First)
                    {
                        SourceMax = tmp;
                        SourceMin = tmp;
                        First = false;
                    }

                    if (tmp > SourceMax)
                        SourceMax = tmp;
                    if (tmp < SourceMin)
                        SourceMin = tmp;

                }
                SourceAve = SourceAve / SRows.Count;

                if (Convertable)
                {
                    Double DestAve = 0;
                    Double DestMax = 0;
                    Double DestMin = 0;
                    First = true;
                    foreach (DataRow Row in DRows)
                    {
                        if (Row[DestColumn].GetType().Name != "DBNull")
                        {
                            Double tmp = Convert.ToDouble(Row[DestColumn]);

                            DestAve += tmp;

                            if (First)
                            {
                                DestMax = tmp;
                                DestMin = tmp;
                                First = false;
                            }

                            if (tmp > DestMax)
                                DestMax = tmp;
                            if (tmp < DestMin)
                                DestMin = tmp;
                        }

                    }

                    DestAve = DestAve / DRows.Count;

                    float AverageMatching = CalcMatching(SourceAve, DestAve);
                    float MinMatching = CalcMatching(SourceMin, DestMin);
                    float MaxMatching = CalcMatching(SourceMax, DestMax);


                    Result = (AverageMatching * 0.4f) + (MinMatching * 0.3f) + (MaxMatching * 0.3f);
                }
            }
#endregion

#region IntToInt
            if (((SourceColumn.DataType.Name == "Int32") || (SourceColumn.DataType.Name == "Int16")) && (DestColumn.DataType.Name == "Int32"))
            {
                Boolean First = true;
                float SourceAve = 0.0f;
                float SourceMin = 0.0f;
                float SourceMax = 0.0f;
                int SourceNull = 0;
                // Maximal ein Komma/Punkt und ein Minus, Wert muss unter Int.Max liegen
                foreach (DataRow Row in SRows)
                {
                    if (Row[SourceColumn].GetType().Name != "DBNull")
                    {
                        int tmp = Convert.ToInt32(Row[SourceColumn]);
                        SourceAve += tmp;

                        if (First)
                        {
                            SourceMax = tmp;
                            SourceMin = tmp;
                            First = false;
                        }

                        if (tmp > SourceMax)
                            SourceMax = tmp;
                        if (tmp < SourceMin)
                            SourceMin = tmp;
                    }
                    else
                        SourceNull++;

                }
                SourceAve = SourceAve / (SRows.Count - SourceNull);

                float DestAve = 0.0f;
                float DestMax = 0.0f;
                float DestMin = 0.0f;
                int DestNull = 0;
                First = true;
                foreach (DataRow Row in DRows)
                {
                    if (Row[DestColumn].GetType().Name != "DBNull")
                    {
                        int tmp = Convert.ToInt32(Row[DestColumn]);

                        DestAve += tmp;

                        if (First)
                        {
                            DestMax = tmp;
                            DestMin = tmp;
                            First = false;
                        }

                        if (tmp > DestMax)
                            DestMax = tmp;
                        if (tmp < DestMin)
                            DestMin = tmp;
                    }
                    else
                        DestNull++;
                }

                DestAve = DestAve / (DRows.Count-DestNull);

                float AverageMatching = CalcMatching(SourceAve, DestAve);
                float MinMatching = CalcMatching(SourceMin, DestMin);
                float MaxMatching = CalcMatching(SourceMax, DestMax);


                Result = (AverageMatching * 0.4f) + (MinMatching * 0.3f) + (MaxMatching * 0.3f);
                
            }
#endregion

            #region Int32ToInt16
            if (((SourceColumn.DataType.Name == "Int32") || (SourceColumn.DataType.Name == "Int16")) && (DestColumn.DataType.Name == "Int16"))
            {
                Boolean First = true;
                float SourceAve = 0.0f;
                float SourceMin = 0.0f;
                float SourceMax = 0.0f;
                int SourceNull = 0;
                // Maximal ein Komma/Punkt und ein Minus, Wert muss unter Int.Max liegen
                foreach (DataRow Row in SRows)
                {
                    if (Row[SourceColumn].GetType().Name != "DBNull")
                    {
                        int tmp = Convert.ToInt32(Row[SourceColumn]);
                        SourceAve += tmp;

                        if (First)
                        {
                            SourceMax = tmp;
                            SourceMin = tmp;
                            First = false;
                        }

                        if (tmp > SourceMax)
                            SourceMax = tmp;
                        if (tmp < SourceMin)
                            SourceMin = tmp;
                    }
                    else
                        SourceNull++;

                }
                SourceAve = SourceAve / (SRows.Count - SourceNull);

                if (SourceMax <= Int16.MaxValue)
                {

                    float DestAve = 0.0f;
                    float DestMax = 0.0f;
                    float DestMin = 0.0f;
                    int DestNull = 0;
                    First = true;
                    foreach (DataRow Row in DRows)
                    {
                        if (Row[DestColumn].GetType().Name != "DBNull")
                        {
                            int tmp = Convert.ToInt32(Row[DestColumn]);

                            DestAve += tmp;

                            if (First)
                            {
                                DestMax = tmp;
                                DestMin = tmp;
                                First = false;
                            }

                            if (tmp > DestMax)
                                DestMax = tmp;
                            if (tmp < DestMin)
                                DestMin = tmp;
                        }
                        else
                            DestNull++;
                    }

                    DestAve = DestAve / (DRows.Count - DestNull);

                    float AverageMatching = CalcMatching(SourceAve, DestAve);
                    float MinMatching = CalcMatching(SourceMin, DestMin);
                    float MaxMatching = CalcMatching(SourceMax, DestMax);


                    Result = (AverageMatching * 0.4f) + (MinMatching * 0.3f) + (MaxMatching * 0.3f);
                }

            }
            #endregion

#region DecimalToInt
            if ((SourceColumn.DataType.Name == "Decimal") && (DestColumn.DataType.Name == "Int32"))
            {
                Boolean First = true;
                float SourceAve = 0.0f;
                float SourceMin = 0.0f;
                float SourceMax = 0.0f;
                int SourceNull = 0;
                // Maximal ein Komma/Punkt und ein Minus, Wert muss unter Int.Max liegen
                foreach (DataRow Row in SRows)
                {
                    if (Row[SourceColumn].GetType().Name != "DBNull")
                    {
                        int tmp = Convert.ToInt32(Row[SourceColumn]);
                        SourceAve += tmp;

                        if (First)
                        {
                            SourceMax = tmp;
                            SourceMin = tmp;
                            First = false;
                        }

                        if (tmp > SourceMax)
                            SourceMax = tmp;
                        if (tmp < SourceMin)
                            SourceMin = tmp;
                    }
                    else
                        SourceNull++;

                }
                SourceAve = SourceAve / (SRows.Count - SourceNull);

                float DestAve = 0.0f;
                float DestMax = 0.0f;
                float DestMin = 0.0f;
                int DestNull = 0;
                First = true;
                foreach (DataRow Row in DRows)
                {
                    if (Row[DestColumn].GetType().Name != "DBNull")
                    {
                        int tmp = Convert.ToInt32(Row[DestColumn]);

                        DestAve += tmp;

                        if (First)
                        {
                            DestMax = tmp;
                            DestMin = tmp;
                            First = false;
                        }

                        if (tmp > DestMax)
                            DestMax = tmp;
                        if (tmp < DestMin)
                            DestMin = tmp;
                    }
                    else
                        DestNull++;
                }

                DestAve = DestAve / (DRows.Count - DestNull);

                float AverageMatching = CalcMatching(SourceAve, DestAve);
                float MinMatching = CalcMatching(SourceMin, DestMin);
                float MaxMatching = CalcMatching(SourceMax, DestMax);


                Result = (AverageMatching * 0.4f) + (MinMatching * 0.3f) + (MaxMatching * 0.3f);

            }
            #endregion

            #region DecimalToInt16
            if ((SourceColumn.DataType.Name == "Decimal") && (DestColumn.DataType.Name == "Int16"))
            {
                Boolean First = true;
                float SourceAve = 0.0f;
                float SourceMin = 0.0f;
                float SourceMax = 0.0f;
                int SourceNull = 0;
                // Maximal ein Komma/Punkt und ein Minus, Wert muss unter Int.Max liegen
                foreach (DataRow Row in SRows)
                {
                    if (Row[SourceColumn].GetType().Name != "DBNull")
                    {
                        int tmp = Convert.ToInt32(Row[SourceColumn]);
                        SourceAve += tmp;

                        if (First)
                        {
                            SourceMax = tmp;
                            SourceMin = tmp;
                            First = false;
                        }

                        if (tmp > SourceMax)
                            SourceMax = tmp;
                        if (tmp < SourceMin)
                            SourceMin = tmp;
                    }
                    else
                        SourceNull++;

                }
                SourceAve = SourceAve / (SRows.Count - SourceNull);

                if (SourceMax < Int16.MaxValue)
                {

                    float DestAve = 0.0f;
                    float DestMax = 0.0f;
                    float DestMin = 0.0f;
                    int DestNull = 0;
                    First = true;
                    foreach (DataRow Row in DRows)
                    {
                        if (Row[DestColumn].GetType().Name != "DBNull")
                        {
                            int tmp = Convert.ToInt32(Row[DestColumn]);

                            DestAve += tmp;

                            if (First)
                            {
                                DestMax = tmp;
                                DestMin = tmp;
                                First = false;
                            }

                            if (tmp > DestMax)
                                DestMax = tmp;
                            if (tmp < DestMin)
                                DestMin = tmp;
                        }
                        else
                            DestNull++;
                    }

                    DestAve = DestAve / (DRows.Count - DestNull);

                    float AverageMatching = CalcMatching(SourceAve, DestAve);
                    float MinMatching = CalcMatching(SourceMin, DestMin);
                    float MaxMatching = CalcMatching(SourceMax, DestMax);


                    Result = (AverageMatching * 0.4f) + (MinMatching * 0.3f) + (MaxMatching * 0.3f);
                }
            }
            #endregion

#region IntToDecimal
            if (((SourceColumn.DataType.Name == "Int32") || (SourceColumn.DataType.Name == "Int16")) && (DestColumn.DataType.Name == "Decimal"))
            {
                Boolean First = true;
                float SourceAve = 0.0f;
                float SourceMin = 0.0f;
                float SourceMax = 0.0f;
                int SourceNull = 0;
                // Maximal ein Komma/Punkt und ein Minus, Wert muss unter Int.Max liegen
                foreach (DataRow Row in SRows)
                {
                    if (Row[SourceColumn].GetType().Name != "DBNull")
                    {
                        int tmp = Convert.ToInt32(Row[SourceColumn]);
                        SourceAve += tmp;

                        if (First)
                        {
                            SourceMax = tmp;
                            SourceMin = tmp;
                            First = false;
                        }

                        if (tmp > SourceMax)
                            SourceMax = tmp;
                        if (tmp < SourceMin)
                            SourceMin = tmp;
                    }
                    else
                        SourceNull++;

                }
                SourceAve = SourceAve / (SRows.Count - SourceNull);

                float DestAve = 0.0f;
                float DestMax = 0.0f;
                float DestMin = 0.0f;
                int DestNull = 0;
                First = true;
                foreach (DataRow Row in DRows)
                {
                    if (Row[DestColumn].GetType().Name != "DBNull")
                    {
                        int tmp = Convert.ToInt32(Row[DestColumn]);

                        DestAve += tmp;

                        if (First)
                        {
                            DestMax = tmp;
                            DestMin = tmp;
                            First = false;
                        }

                        if (tmp > DestMax)
                            DestMax = tmp;
                        if (tmp < DestMin)
                            DestMin = tmp;
                    }
                    else
                        DestNull++;
                }

                DestAve = DestAve / (DRows.Count - DestNull);

                float AverageMatching = CalcMatching(SourceAve, DestAve);
                float MinMatching = CalcMatching(SourceMin, DestMin);
                float MaxMatching = CalcMatching(SourceMax, DestMax);


                Result = (AverageMatching * 0.4f) + (MinMatching * 0.3f) + (MaxMatching * 0.3f);

            }
            #endregion

#region DecimalToDecimal
            if ((SourceColumn.DataType.Name == "Decimal") && (DestColumn.DataType.Name == "Decimal"))
            {
                Boolean First = true;
                float SourceAve = 0.0f;
                float SourceMin = 0.0f;
                float SourceMax = 0.0f;
                int SourceNull = 0;
                // Maximal ein Komma/Punkt und ein Minus, Wert muss unter Int.Max liegen
                foreach (DataRow Row in SRows)
                {
                    if (Row[SourceColumn].GetType().Name != "DBNull")
                    {
                        int tmp = Convert.ToInt32(Row[SourceColumn]);
                        SourceAve += tmp;

                        if (First)
                        {
                            SourceMax = tmp;
                            SourceMin = tmp;
                            First = false;
                        }

                        if (tmp > SourceMax)
                            SourceMax = tmp;
                        if (tmp < SourceMin)
                            SourceMin = tmp;
                    }
                    else
                        SourceNull++;

                }
                SourceAve = SourceAve / (SRows.Count - SourceNull);

                float DestAve = 0.0f;
                float DestMax = 0.0f;
                float DestMin = 0.0f;
                int DestNull = 0;
                First = true;
                foreach (DataRow Row in DRows)
                {
                    if (Row[DestColumn].GetType().Name != "DBNull")
                    {
                        int tmp = Convert.ToInt32(Row[DestColumn]);

                        DestAve += tmp;

                        if (First)
                        {
                            DestMax = tmp;
                            DestMin = tmp;
                            First = false;
                        }

                        if (tmp > DestMax)
                            DestMax = tmp;
                        if (tmp < DestMin)
                            DestMin = tmp;
                    }
                    else
                        DestNull++;
                }

                DestAve = DestAve / (DRows.Count - DestNull);

                float AverageMatching = CalcMatching(SourceAve, DestAve);
                float MinMatching = CalcMatching(SourceMin, DestMin);
                float MaxMatching = CalcMatching(SourceMax, DestMax);


                Result = (AverageMatching * 0.4f) + (MinMatching * 0.3f) + (MaxMatching * 0.3f);

            }
            #endregion

#region StringToString
            if ((SourceColumn.DataType.Name == "String") && (DestColumn.DataType.Name == "String"))
            {
                int Count = 0;
                float DiceSum = 0.0f;
                // Maximal ein Komma/Punkt und ein Minus, Wert muss unter Int.Max liegen
                foreach (DataRow SRow in SRows)
                {
                    foreach (DataRow DRow in DRows)
                    {
                        DiceSum += Dice(SRow[SourceColumn].ToString(), DRow[DestColumn].ToString());
                        Count++;
                    }

                }



                Result = DiceSum/Count;

            }
            #endregion

#region IntToString
            // String auf Integer
            if (((SourceColumn.DataType.Name == "Int32") || (SourceColumn.DataType.Name == "Int16")) && (DestColumn.DataType.Name == "String"))
            {
                // Strings können nach Int konvertiert werden!?
                Boolean Convertable = true;
                Boolean First = true;
                float DestAve = 0;
                int DestMax = 0;
                int DestMin = 0;

                // Maximal ein Komma/Punkt und ein Minus, Wert muss unter Int.Max liegen
                foreach (DataRow Row in DRows)
                {
                    Boolean Valid = ConvertableStringToDecimal(Row[DestColumn], false, true);

                    if (!Valid)
                    {
                        Convertable = false;
                        break;
                    }
                    int tmp = Convert.ToInt32(Row[DestColumn]);
                    DestAve += tmp;

                    if (First)
                    {
                        DestMax = tmp;
                        DestMin = tmp;
                        First = false;
                    }

                    if (tmp > DestMax)
                        DestMax = tmp;
                    if (tmp < DestMin)
                        DestMin = tmp;

                }
                DestAve = DestAve / DRows.Count;

                if (Convertable)
                {
                    float SourceAve = 0;
                    int SourceMax = 0;
                    int SourceMin = 0;
                    First = true;
                    foreach (DataRow Row in SRows)
                    {
                        if (Row[SourceColumn].GetType().Name != "DBNull")
                        {
                            int tmp = Convert.ToInt32(Row[SourceColumn]);

                            SourceAve += tmp;

                            if (First)
                            {
                                SourceMax = tmp;
                                SourceMin = tmp;
                                First = false;
                            }

                            if (tmp > SourceMax)
                                SourceMax = tmp;
                            if (tmp < SourceMin)
                                SourceMin = tmp;
                        }

                    }

                    SourceAve = SourceAve / SRows.Count;

                    float AverageMatching = CalcMatching(SourceAve, DestAve);
                    float MinMatching = CalcMatching(SourceMin, DestMin);
                    float MaxMatching = CalcMatching(SourceMax, DestMax);


                    Result = (AverageMatching * 0.4f) + (MinMatching * 0.3f) + (MaxMatching * 0.3f);
                }
            }
            #endregion

#region DecimalToString
            // String auf Integer
            if ((SourceColumn.DataType.Name == "Decimal") && (DestColumn.DataType.Name == "String"))
            {
                // Strings können nach Int konvertiert werden!?
                Boolean Convertable = true;
                Boolean First = true;
                Double DestAve = 0;
                Double DestMax = 0;
                Double DestMin = 0;

                // Maximal ein Komma/Punkt und ein Minus, Wert muss unter Int.Max liegen
                foreach (DataRow Row in DRows)
                {
                    Boolean Valid = ConvertableStringToDecimal(Row[DestColumn], false, true);

                    if (!Valid)
                    {
                        Convertable = false;
                        break;
                    }
                    Double tmp = Convert.ToDouble(Row[DestColumn]);
                    DestAve += tmp;

                    if (First)
                    {
                        DestMax = tmp;
                        DestMin = tmp;
                        First = false;
                    }

                    if (tmp > DestMax)
                        DestMax = tmp;
                    if (tmp < DestMin)
                        DestMin = tmp;

                }
                DestAve = DestAve / DRows.Count;

                if (Convertable)
                {
                    Double SourceAve = 0;
                    Double SourceMax = 0;
                    Double SourceMin = 0;
                    First = true;
                    foreach (DataRow Row in SRows)
                    {
                        if (Row[SourceColumn].GetType().Name != "DBNull")
                        {
                            Double tmp = Convert.ToDouble(Row[SourceColumn]);

                            SourceAve += tmp;

                            if (First)
                            {
                                SourceMax = tmp;
                                SourceMin = tmp;
                                First = false;
                            }

                            if (tmp > SourceMax)
                                SourceMax = tmp;
                            if (tmp < SourceMin)
                                SourceMin = tmp;
                        }

                    }

                    SourceAve = SourceAve / SRows.Count;

                    float AverageMatching = CalcMatching(SourceAve, DestAve);
                    float MinMatching = CalcMatching(SourceMin, DestMin);
                    float MaxMatching = CalcMatching(SourceMax, DestMax);


                    Result = (AverageMatching * 0.4f) + (MinMatching * 0.3f) + (MaxMatching * 0.3f);
                }
            }
            #endregion

            if (Result >= 0f && Result <= 1f)
                return Result;
            else
                return 0f;
        }

        private float Dice(String A, String B)
        {
            String sA = A.ToLower();
            String sB = B.ToLower();
            String[] N_A;
            String[] N_B;

            sA = sA.Insert(0, "$$");
            sA = sA.Insert(sA.Length, "$$");
            sB = sB.Insert(0, "$$");
            sB = sB.Insert(sB.Length, "$$");
            N_A = new String[sA.Length - 2];
            N_B = new String[sB.Length - 2];
            for (int i = 0; i < N_A.Length; i++)
                N_A[i] = sA.Substring(i, 3);
            for (int i = 0; i < N_B.Length; i++)
                N_B[i] = sB.Substring(i, 3);
            int Matches = 0;
            foreach (String SubA in N_A)
                foreach (String SubB in N_B)
                    if (String.Compare(SubA, SubB) == 0)
                        Matches++;
            return ((2.0f * Matches) / (N_A.Length + N_B.Length));
        }



    }
}
